home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Risc World 3
/
Risc World 3.iso
/
SOFTWARE
/
ISSUE6
/
PD
/
PDF
/
GuiLib
/
GuiFlex
/
c++
/
GuiFlexDA
< prev
next >
Wrap
Text File
|
2003-02-14
|
7KB
|
296 lines
//--------------------------------------------------------------------------
//
// Copyright (c) 2002, Colin Granville
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// * The name Colin Granville may not be used to endorse or promote
// products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//
//--------------------------------------------------------------------------
#include "GuiFlexDA.h"
#include "fstream.h"
#include "swis.h"
#include <string.h>
inline int align(int n) {return ((n+3)&~3);}
inline int objectdif(GuiFlexDA::Object* a,GuiFlexDA::Object* b) {return ((char*)a) - ((char*)b);}
GuiFlexDA::GuiFlexDA(const char *name, int* /*error_fd*/, int dynamic_size)
: base(0),
top(0),
end(0)
{
_swix(OS_DynamicArea,_INR(0,8)| _OUT(1) | _OUT(3) | _OUT(5),
0,
-1,
0,
-1,
(1<<7),
dynamic_size,
0,
0,
(name ? name:"GuiFlexDA"),
&number,
&base,
&maxSize
);
}
//**************************************************************
GuiFlexDA::~GuiFlexDA()
{
atExit();
}
//**************************************************************
inline GuiFlexDA::Object* GuiFlexDA::nextObject(GuiFlexDA::Object* ob)
{
return (GuiFlexDA::Object*)( ((char*)ob)+ob->capacity()+sizeof(GuiFlexDA::Object) );
}
//**************************************************************
inline GuiFlexDA::Object* GuiFlexDA::topObject()
{
return (GuiFlexDA::Object*)(base+top);
}
//**************************************************************
inline GuiFlexDA::Object* GuiFlexDA::getObject(const GuiFlexAnchor& anchor) const
{
Object* ob=0;
if (isOk() &&
((size_t)anchor.data & 3)==0 &&
anchor.data>base && anchor.data< base+end )
{
ob=((Object*)anchor.data)-1;
if (ob->anchor != &anchor) ob=0;
}
return ob;
}
//**************************************************************
inline void GuiFlexDA::setAnchor(GuiFlexAnchor& anchor,Object* object)
{
anchor.data=(char*)(object+1);
object->anchor=&anchor;
}
//**************************************************************
void GuiFlexDA::reanchor(Object* from)
{
Object* to = topObject();
while (from!=to)
{
from->anchor->data=(char*)(from+1);
from=nextObject(from);
}
}
//**************************************************************
bool GuiFlexDA::resize(size_t new_size)
{
if (!isOk() && new_size>maxSize) return 0;
new_size=align(new_size);
int by=new_size-end;
int moved=0;
if (_swix(OS_ChangeDynamicArea,_INR(0,1)|_OUT(1),number,by,&moved) ||
(moved==0 && by>0) ) return 0;
if (by>0) end+=moved; else end-=moved;
return 1;
}
//**************************************************************
bool GuiFlexDA::alloc(GuiFlexAnchor& anchor,size_t n)
{
if (!isOk()) return 0;
size_t new_top = top+align(n+sizeof(Object));
if (new_top>end && !resize(new_top)) return 0;
Object* ob = topObject();
top=new_top;
ob->size=n;
setAnchor(anchor,ob);
return 1;
}
//**************************************************************
bool GuiFlexDA::free(GuiFlexAnchor& anchor)
{
Object* ob=getObject(anchor);
if (ob==0) return 0;
Object* next=nextObject(ob);
memmove(ob,next,objectdif(topObject(),next));
top+=objectdif(ob,next);
reanchor(ob);
resize(top);
anchor.data=0;
return 1;
}
//**************************************************************
size_t GuiFlexDA::size(const GuiFlexAnchor& anchor) const
{
Object* ob=getObject(anchor);
return ob==0 ? 0 : ob->size;
}
//**************************************************************
bool GuiFlexDA::extend(GuiFlexAnchor& anchor,size_t new_size)
{
Object* ob=getObject(anchor);
if (ob==0) return 0;
int by=align(new_size-ob->capacity());
if (by==0)
{
ob->size=new_size;
return 1;
}
if (by>0)
{
if (!resize(top+by)) return 0;
Object* next=nextObject(ob);
memmove(((char*)next)+by,next,objectdif(topObject(),next));
}
else
{
Object* next=nextObject(ob);
memmove(((char*)next)+by,next,objectdif(topObject(),next));
if (!resize(top+by)) return 0;
}
ob->size=new_size;
top+=by;
reanchor(nextObject(ob));
return 1;
}
//**************************************************************
bool GuiFlexDA::midExtend(GuiFlexAnchor& anchor,size_t at,int by)
{
Object* ob=getObject(anchor);
if (ob==0) return 0;
if (by==0) return 1;
if (at>=ob->size)
{
if (by<0 && at<-by) by=-at;
return extend(anchor,at+by);
}
if (by>0)
{
if (!extend(anchor,ob->size+by)) return 0;
memmove(anchor.data+at+by,anchor.data+at,ob->size-at-by);
}
else
{
memmove(anchor.data+at+by,anchor.data+at,ob->size-at);
extend(anchor,ob->size+by);
}
return 1;
}
//**************************************************************
bool GuiFlexDA::reanchor(GuiFlexAnchor& to, GuiFlexAnchor& from)
{
Object* ob=getObject(from);
if (ob==0) return 0;
setAnchor(to,ob);
from.data=0;
return 1;
}
//**************************************************************
bool GuiFlexDA::setBudge(bool on)
{
return on;
}
//**************************************************************
void GuiFlexDA::saveHeapInfo(char* filename)
{
ofstream out(filename);
if (!out) return;
out << "GuiFlexDA::saveHeapInfo not implemented" << endl;
}
//**************************************************************
bool GuiFlexDA::compact()
{
return 0;
}
//**************************************************************
bool GuiFlexDA::setDeferredCompaction(bool on)
{
return on;
}
//**************************************************************
size_t GuiFlexDA::availableMemory()
{
size_t freesize=0;
_swix(Wimp_SlotSize,_INR(0,1) | _OUT(2),-1,-1,&freesize);
if (freesize+end > maxSize) freesize=maxSize-end;
return (freesize+end-top);
}
//**************************************************************
void GuiFlexDA::atExit()
{
if (base) _swix(OS_DynamicArea,_INR(0,1),1,number);
}